import 'package:flutter/material.dart';
import 'package:get/get.dart';

///跨组件状态共享Provider
///原则：如果状态是组件私有的，则应该由组件自己管理；如果状态要跨组件共享，则该
///     状态应该由各个组件共同的父元素来管理。对于组件私有的状态管理很好理解，
///     但对于跨组件共享的状态，管理的方式就比较多，如使用全局事件总线EventBus，
///     它是一个观察者模式的实现，通过它就可以实现跨组件状态同步：状态持有方(发布者)
///     负责更新、发布状态、状态使用方(观察者)监听状态改变事件来执行一些操作。
///观察者模式实现跨组件状态缺点：
///1、必须显式定义各种事件，不好管理。
///2、订阅者必须需显式注册状态改变回调，也必须在组件销毁时手动去解绑回调以避免内存泄漏。
///使用Provider优势：
///1、业务代码更关注数据，只要更新Model，则UI会自动更新，而不用在状态改变后再去手动调用
///   setState()来显式更新页面。
///2、数据改变的消息传递被屏蔽了，我们无需手动去处理状态改变事件的发布和订阅，这一切都被
///   封装在Provider中。
///3、在大型复杂应用中，尤其是需要全局共享的状态非常多时，使用Provider将会大大简化我们的
///   代码逻辑，降低出错的概率，提高开发效率。
///注意：
///   未找到本地持久化方式，似乎只能作为局部刷新方案
class ProviderPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _InheritedWidget();
// State<StatefulWidget> createState() => _InheritedWidgetTestRouteState();
}

///Provier方式
class InheritedProvider<T> extends InheritedWidget {
  final T? data;

  InheritedProvider({this.data, required Widget child}) : super(child: child);

  @override
  bool updateShouldNotify(covariant InheritedWidget oldWidget) => true;
}

class ChangeNotifierProvider<T extends ChangeNotifier> extends StatefulWidget {
  final Widget? child;
  final T? data;

  ChangeNotifierProvider({Key? key, this.data, this.child});

  static T? of<T>(BuildContext context, {bool listen = true}) {
    // final provider = context.dependOnInheritedWidgetOfExactType<InheritedProvider<T>>();
    final provider = listen
        ? context.dependOnInheritedWidgetOfExactType<InheritedProvider<T>>()
        : context
            .getElementForInheritedWidgetOfExactType<InheritedProvider<T>>()
            ?.widget as InheritedProvider<T>;
    return provider?.data;
  }

  @override
  _ChangeNotifierProviderState<T> createState() =>
      _ChangeNotifierProviderState<T>();
}

class _ChangeNotifierProviderState<T extends ChangeNotifier>
    extends State<ChangeNotifierProvider<T>> {
  void update() {
    setState(() {});
  }

  @override
  void didUpdateWidget(covariant ChangeNotifierProvider<T> oldWidget) {
    if (widget.data != oldWidget.data) {
      oldWidget.data?.removeListener(update);
      widget.data?.addListener(update);
    }
    super.didUpdateWidget(oldWidget);
    print('didUpdateWidget');
  }

  @override
  void initState() {
    widget.data?.addListener(update);
    super.initState();
  }

  @override
  void dispose() {
    widget.data?.removeListener(update);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return InheritedProvider<T>(
      data: widget.data,
      child: widget.child!,
    );
  }
}

class CartModel extends ChangeNotifier {
  final List<int> _items = [];

  int _count = 0;

  // int get totalPrice =>
  //     _items.fold(0, (previousValue, element) => previousValue + element);

  void add(int item) {
    // _items.add(item);
    _count -= item;
    notifyListeners();
  }
}

// class ChangeNotifier implements Listenable {
//   List listeners = [];
//
//   @override
//   void addListener(listener) {
//     listeners.add(listener);
//   }
//
//   @override
//   void removeListener(listener) {
//     listeners.remove(listener);
//   }
//
//   void notifyListeners() {
//     listeners.forEach((listener) => listener());
//   }
// }

///setState()刷新


class Controller extends GetxController{
  var _counter = 0.obs();
  add() => _counter++;
}

///Provider数据共享
class _InheritedWidget extends State<ProviderPage> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("状态管理"),
      ),
      body: Container(
        alignment: Alignment.center,
        // child: InkWell(
        //   onTap: (){
        //     c.add();
        //     print("总价：${c._counter}");
        //   },
        //   child: Text("点击"),
        // ),
        // child: InkWell(
        //   onTap: () {
        //     setState(() {
        //       ++count;
        //     });
        //   },
        //   child: Text('总价:$count'),
        // ),
        // child: ChangeNotifierProvider<CartModel>(
        //   data: CartModel(),
        //   child: Builder(
        //     builder: (context) {
        //       return InkWell(
        //         onTap: () {
        //           ChangeNotifierProvider.of<CartModel>(context)?.add(10);
        //         },
        //         child: Builder(
        //           builder: (context) {
        //             var cart = ChangeNotifierProvider.of<CartModel>(context,
        //                 listen: false);
        //             return Text('总价:${cart?._count}');
        //           },
        //         ),
        //       );
        //     },
        //   ),
        // ),

        ///Provider刷新有局限性：如果没有包裹在ChangeNotifierProvider中，则无法刷新界面
        ///相当于发送者和接收者必须在同一个ChangeNotifierProvider中，而且刷新ChangeNotifierProvider
        ///里面的Widget全部都刷新了
        child: Row(
          children: [
            GestureDetector(
              onTap: () {
                print("点击添加");
                ChangeNotifierProvider.of<CartModel>(context)?.add(10);
              },
              child: Text('添加'),
            ),
            ChangeNotifierProvider<CartModel>(
              data: CartModel(),
              child: Builder(
                builder: (context) {
                  var model = ChangeNotifierProvider.of<CartModel>(context, listen: false);
                  return Text('总价：${model?._count}');
                },
              ),
            )
          ],
        ),
      ),
    );
  }
}

class _TestWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => __TestWidgetState();
}

class __TestWidgetState extends State<_TestWidget> {
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    //父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用.
    //如果build中没有依赖InheritedWidget，则此回调不会被调用。
    print("====didChangeDependencies");
  }

  @override
  Widget build(BuildContext context) {
    return Text('count:${ShareDataWidget.of(context)?.data}');
    // return Text('text');
  }
}

class ShareDataWidget extends InheritedWidget {
  int data = 0; //需要在子树中共享的数据，保存点击次数

  ShareDataWidget({Key? key, this.data = 0, required Widget child})
      : super(key: key, child: child);

  //定义一个便捷方法，方便子树种的widget获取共享数据
  static ShareDataWidget? of(BuildContext context) {
    // return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
    return context
        .getElementForInheritedWidgetOfExactType<ShareDataWidget>()
        ?.widget as ShareDataWidget; //使用此方式无组件依赖
  }

  //该回调决定当data放生变化时，是否通知子树种依赖data的widget重新build
  @override
  bool updateShouldNotify(covariant ShareDataWidget oldWidget) {
    return oldWidget.data != data;
  }
}

class _InheritedWidgetTestRouteState extends State<ProviderPage> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ShareDataWidget(
        data: count,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Padding(
              padding: const EdgeInsets.only(bottom: 20.0),
              child: _TestWidget(),
            ),
            ElevatedButton(
                onPressed: () => {
                      print('count:$count'),
                      setState(() {
                        ++count;
                      })
                    },
                child: Text('add')),
          ],
        ),
      ),
    );
  }
}
